/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package model.creature.plant;

import java.awt.Image;
import java.util.ArrayList;
import model.creature.Crystal;
import model.game.GameInterface;
import model.map.cell.PlantableCell;

/**
 *
 * @author dolphinigle
 */
public abstract class AOEHealerPlant extends MultiHarvestPlant {

  /**
   * Constructor
   */
  public AOEHealerPlant(GameInterface game, PlantableCell cell) {
    super(game, cell);
  }

  /**
   * Advances time and attack monsters
   */
  @Override
  public void advanceTime() {
    if (!canHeal()) return;

    int maxcnt = getHealCount();

    ArrayList<Crystal> crystals_ =
            (ArrayList<Crystal>)game_.getCreatures().getCrystals().getAllCrystals().clone();

    for (Crystal crystal : crystals_) {
      if (maxcnt <= 0) break;
      int manhattandistance = Math.abs(crystal.getCell().getX() -
              getCell().getX()) + Math.abs(crystal.getCell().getY() -
              getCell().getY());
      if (manhattandistance <= getCrystalRadius()) {
        int old_hp = crystal.getHP();
        crystal.heal(getHealPower());
        if (crystal.getHP() != old_hp) {
          --maxcnt;
          game_.addMessage(this.getName() + " heals " + crystal.getName() +
                " by " + (crystal.getHP() - old_hp));
        }
      }
    }

    ArrayList<Plant> plants =
            (ArrayList<Plant>)game_.getCreatures().getPlants().getAllPlants().clone();

    for (Plant plant : plants) {
      if (maxcnt <= 0) break;
      int manhattandistance = Math.abs(plant.getCell().getX() -
              getCell().getX()) + Math.abs(plant.getCell().getY() -
              getCell().getY());
      if (manhattandistance <= getRadius()) {
        int old_hp = plant.getHP();
        plant.heal(getHealPower());
        if (plant.getHP() != old_hp) {
          --maxcnt;
          game_.addMessage(this.getName() + " heals " + plant.getName() +
                " by " + (plant.getHP() - old_hp));
        }
      }
    }
  }

  /**
   * Returns true iff plant can heal now. By default set to true only at day
   * and when is harvestable
   */
  public boolean canHeal() {
    return isHarvestable() && game_.isNight() == false;
  }
  /**
   * Retrieves the fruit name from this plant when harvested
   */
  @Override
  protected abstract String getFruitName();

  /**
   * Retrieves the days required to go from seed to mature
   */
  @Override
  protected abstract int timeToMature();

  /**
   * Retrieves the days before this plant dies
   */
  @Override
  protected abstract int timeToDie();

  /**
   * Retrieves the days before this plant can be harvested from mature state,
   * having beeing harvested harvest_count times before
   */
  @Override
  protected abstract int timeToHarvest(int harvest_count);

  /**
   * Retrieves the HP of this plant at the given level
   * level can be accessed through getLevel()
   */
  @Override
  protected abstract int getHPAtCurrentLevel();

  /**
   * Returns true iff plant can be upgraded again now
   * It's current level is given in getLevel()
   */
  @Override
  public abstract boolean canUpgrade();

  /**
   * Retrieves the price to upgrade this plant's level
   * It's current level is given in getLevel()
   * @requires canUpgrade()
   */
  @Override
  public abstract int getUpgradeCost();

   /**
   * Returns the image sprite of this plant
   */
  @Override
  public abstract Image getImage();

  /**
   * Returns the name of this plant
   * Primary Key
   */
  @Override
  public abstract String getName();

  /**
   * Return the season only during this season this plant may grow
   */
  @Override
  public abstract String getSeason();

  /**
   * Returns the description of this plant
   */
  @Override
  public abstract String getDescription();

  /**
   * Returns the radius of this plant's attacks
   *
   * I.e., this plant attack at most plantAttackCount() monsters whose
   * manhattan distance with this plant is less than or equal getRadius()
   */
  public abstract int getRadius();

  /**
   * Returns the number of shots this plant performs each time.
   */
  public abstract int getHealCount();

  /**
   * Returns the amount of HP restored each healing
   */
  public abstract int getHealPower();

  /**
   * Returns the radius of this plant's healing towards a crystal
   */
  public abstract int getCrystalRadius();

}
